/*
 * This file is part of the openHiTLS project.
 *
 * openHiTLS is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "hitls_build.h"
#ifdef HITLS_CRYPTO_ECC

#include "securec.h"
#include "bsl_sal.h"
#include "bsl_err_internal.h"
#include "crypt_utils.h"
#include "crypt_errno.h"
#include "ecc_local.h"
#include "crypt_types.h"
#include "crypt_params_key.h"
#include "crypt_ecc_pkey.h"

typedef struct {
    const uint8_t *data;
    uint32_t dataLen;
} ECC_ReadData;

typedef struct {
    ECC_ReadData p;
    ECC_ReadData a;
    ECC_ReadData b;
    ECC_ReadData n;
    ECC_ReadData h;
    ECC_ReadData x;
    ECC_ReadData y;
} CURVE_Para;

#if defined(HITLS_CRYPTO_CURVE_NISTP224) || defined(HITLS_CRYPTO_CURVE_NISTP256) || \
    defined(HITLS_CRYPTO_CURVE_NISTP384) || defined(HITLS_CRYPTO_CURVE_NISTP521) || \
    defined(HITLS_CRYPTO_CURVE_SM2)
static const uint8_t NIST_P_H[] = {
    0x01
};
#endif

#ifdef HITLS_CRYPTO_CURVE_NISTP224
static const uint8_t NIST_P224_P[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};

static const uint8_t NIST_P224_A[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe
};

static const uint8_t NIST_P224_B[] = {
    0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7,
    0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4
};

static const uint8_t NIST_P224_X[] = {
    0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
    0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21
};

static const uint8_t NIST_P224_Y[] = {
    0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0,
    0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34
};

static const uint8_t NIST_P224_N[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
    0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d
};
#endif

#ifdef HITLS_CRYPTO_CURVE_NISTP256
static const uint8_t NIST_P256_P[] = {
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

static const uint8_t NIST_P256_A[] = {
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc
};

static const uint8_t NIST_P256_B[] = {
    0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc,
    0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b
};

static const uint8_t NIST_P256_X[] = {
    0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
    0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96
};

static const uint8_t NIST_P256_Y[] = {
    0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
    0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
};

static const uint8_t NIST_P256_N[] = {
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51
};
#endif

#ifdef HITLS_CRYPTO_CURVE_NISTP384
static const uint8_t NIST_P384_P[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};

static const uint8_t NIST_P384_A[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc
};

static const uint8_t NIST_P384_B[] = {
    0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19,
    0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a,
    0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef
};

static const uint8_t NIST_P384_X[] = {
    0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74,
    0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38,
    0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7
};

static const uint8_t NIST_P384_Y[] = {
    0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29,
    0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0,
    0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f
};

static const uint8_t NIST_P384_N[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf,
    0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73
};
#endif

#ifdef HITLS_CRYPTO_CURVE_NISTP521
static const uint8_t NIST_P521_P[] = {
    0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff
};

static const uint8_t NIST_P521_A[] = {
    0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xfc
};

static const uint8_t NIST_P521_B[] = {
    0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85,
    0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1,
    0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1,
    0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50,
    0x3f, 0x00
};

static const uint8_t NIST_P521_X[] = {
    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
    0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
    0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
    0xbd, 0x66
};

static const uint8_t NIST_P521_Y[] = {
    0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
    0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
    0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
    0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
    0x66, 0x50
};

static const uint8_t NIST_P521_N[] = {
    0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09,
    0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38,
    0x64, 0x09
};
#endif

#if defined(HITLS_CRYPTO_CURVE_BP256R1) || defined(HITLS_CRYPTO_CURVE_BP384R1) || defined(HITLS_CRYPTO_CURVE_BP512R1)
static const uint8_t BRAINPOOL_P_H[] = {
    0x01
};
#endif

#ifdef HITLS_CRYPTO_CURVE_BP256R1
static const uint8_t BRAINPOOL_P256R1_P[] = {
    0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66, 0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x72,
    0x6e, 0x3b, 0xf6, 0x23, 0xd5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1d, 0x1f, 0x6e, 0x53, 0x77
};

static const uint8_t BRAINPOOL_P256R1_A[] = {
    0x7d, 0x5a, 0x09, 0x75, 0xfc, 0x2c, 0x30, 0x57, 0xee, 0xf6, 0x75, 0x30, 0x41, 0x7a, 0xff, 0xe7,
    0xfb, 0x80, 0x55, 0xc1, 0x26, 0xdc, 0x5c, 0x6c, 0xe9, 0x4a, 0x4b, 0x44, 0xf3, 0x30, 0xb5, 0xd9
};

static const uint8_t BRAINPOOL_P256R1_B[] = {
    0x26, 0xdc, 0x5c, 0x6c, 0xe9, 0x4a, 0x4b, 0x44, 0xf3, 0x30, 0xb5, 0xd9, 0xbb, 0xd7, 0x7c, 0xbf,
    0x95, 0x84, 0x16, 0x29, 0x5c, 0xf7, 0xe1, 0xce, 0x6b, 0xcc, 0xdc, 0x18, 0xff, 0x8c, 0x07, 0xb6
};

static const uint8_t BRAINPOOL_P256R1_X[] = {
    0x8b, 0xd2, 0xae, 0xb9, 0xcb, 0x7e, 0x57, 0xcb, 0x2c, 0x4b, 0x48, 0x2f, 0xfc, 0x81, 0xb7, 0xaf,
    0xb9, 0xde, 0x27, 0xe1, 0xe3, 0xbd, 0x23, 0xc2, 0x3a, 0x44, 0x53, 0xbd, 0x9a, 0xce, 0x32, 0x62
};

static const uint8_t BRAINPOOL_P256R1_Y[] = {
    0x54, 0x7e, 0xf8, 0x35, 0xc3, 0xda, 0xc4, 0xfd, 0x97, 0xf8, 0x46, 0x1a, 0x14, 0x61, 0x1d, 0xc9,
    0xc2, 0x77, 0x45, 0x13, 0x2d, 0xed, 0x8e, 0x54, 0x5c, 0x1d, 0x54, 0xc7, 0x2f, 0x04, 0x69, 0x97
};

static const uint8_t BRAINPOOL_P256R1_N[] = {
    0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66, 0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x71,
    0x8c, 0x39, 0x7a, 0xa3, 0xb5, 0x61, 0xa6, 0xf7, 0x90, 0x1e, 0x0e, 0x82, 0x97, 0x48, 0x56, 0xa7
};
#endif

#ifdef HITLS_CRYPTO_CURVE_BP384R1
static const uint8_t BRAINPOOL_P384R1_P[] = {
    0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d, 0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf,
    0x15, 0x2f, 0x71, 0x09, 0xed, 0x54, 0x56, 0xb4, 0x12, 0xb1, 0xda, 0x19, 0x7f, 0xb7, 0x11, 0x23,
    0xac, 0xd3, 0xa7, 0x29, 0x90, 0x1d, 0x1a, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xec, 0x53
};

static const uint8_t BRAINPOOL_P384R1_A[] = {
    0x7b, 0xc3, 0x82, 0xc6, 0x3d, 0x8c, 0x15, 0x0c, 0x3c, 0x72, 0x08, 0x0a, 0xce, 0x05, 0xaf, 0xa0,
    0xc2, 0xbe, 0xa2, 0x8e, 0x4f, 0xb2, 0x27, 0x87, 0x13, 0x91, 0x65, 0xef, 0xba, 0x91, 0xf9, 0x0f,
    0x8a, 0xa5, 0x81, 0x4a, 0x50, 0x3a, 0xd4, 0xeb, 0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26
};

static const uint8_t BRAINPOOL_P384R1_B[] = {
    0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26, 0x8b, 0x39, 0xb5, 0x54, 0x16, 0xf0, 0x44, 0x7c,
    0x2f, 0xb7, 0x7d, 0xe1, 0x07, 0xdc, 0xd2, 0xa6, 0x2e, 0x88, 0x0e, 0xa5, 0x3e, 0xeb, 0x62, 0xd5,
    0x7c, 0xb4, 0x39, 0x02, 0x95, 0xdb, 0xc9, 0x94, 0x3a, 0xb7, 0x86, 0x96, 0xfa, 0x50, 0x4c, 0x11
};

static const uint8_t BRAINPOOL_P384R1_X[] = {
    0x1d, 0x1c, 0x64, 0xf0, 0x68, 0xcf, 0x45, 0xff, 0xa2, 0xa6, 0x3a, 0x81, 0xb7, 0xc1, 0x3f, 0x6b,
    0x88, 0x47, 0xa3, 0xe7, 0x7e, 0xf1, 0x4f, 0xe3, 0xdb, 0x7f, 0xca, 0xfe, 0x0c, 0xbd, 0x10, 0xe8,
    0xe8, 0x26, 0xe0, 0x34, 0x36, 0xd6, 0x46, 0xaa, 0xef, 0x87, 0xb2, 0xe2, 0x47, 0xd4, 0xaf, 0x1e
};

static const uint8_t BRAINPOOL_P384R1_Y[] = {
    0x8a, 0xbe, 0x1d, 0x75, 0x20, 0xf9, 0xc2, 0xa4, 0x5c, 0xb1, 0xeb, 0x8e, 0x95, 0xcf, 0xd5, 0x52,
    0x62, 0xb7, 0x0b, 0x29, 0xfe, 0xec, 0x58, 0x64, 0xe1, 0x9c, 0x05, 0x4f, 0xf9, 0x91, 0x29, 0x28,
    0x0e, 0x46, 0x46, 0x21, 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3c, 0x53, 0x15
};

static const uint8_t BRAINPOOL_P384R1_N[] = {
    0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d, 0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf,
    0x15, 0x2f, 0x71, 0x09, 0xed, 0x54, 0x56, 0xb3, 0x1f, 0x16, 0x6e, 0x6c, 0xac, 0x04, 0x25, 0xa7,
    0xcf, 0x3a, 0xb6, 0xaf, 0x6b, 0x7f, 0xc3, 0x10, 0x3b, 0x88, 0x32, 0x02, 0xe9, 0x04, 0x65, 0x65
};
#endif

#ifdef HITLS_CRYPTO_CURVE_BP512R1
static const uint8_t BRAINPOOL_P512R1_P[] = {
    0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4, 0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07,
    0xcb, 0x30, 0x8d, 0xb3, 0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33, 0x08, 0x71,
    0x7d, 0x4d, 0x9b, 0x00, 0x9b, 0xc6, 0x68, 0x42, 0xae, 0xcd, 0xa1, 0x2a, 0xe6, 0xa3, 0x80, 0xe6,
    0x28, 0x81, 0xff, 0x2f, 0x2d, 0x82, 0xc6, 0x85, 0x28, 0xaa, 0x60, 0x56, 0x58, 0x3a, 0x48, 0xf3
};

static const uint8_t BRAINPOOL_P512R1_A[] = {
    0x78, 0x30, 0xa3, 0x31, 0x8b, 0x60, 0x3b, 0x89, 0xe2, 0x32, 0x71, 0x45, 0xac, 0x23, 0x4c, 0xc5,
    0x94, 0xcb, 0xdd, 0x8d, 0x3d, 0xf9, 0x16, 0x10, 0xa8, 0x34, 0x41, 0xca, 0xea, 0x98, 0x63, 0xbc,
    0x2d, 0xed, 0x5d, 0x5a, 0xa8, 0x25, 0x3a, 0xa1, 0x0a, 0x2e, 0xf1, 0xc9, 0x8b, 0x9a, 0xc8, 0xb5,
    0x7f, 0x11, 0x17, 0xa7, 0x2b, 0xf2, 0xc7, 0xb9, 0xe7, 0xc1, 0xac, 0x4d, 0x77, 0xfc, 0x94, 0xca
};

static const uint8_t BRAINPOOL_P512R1_B[] = {
    0x3d, 0xf9, 0x16, 0x10, 0xa8, 0x34, 0x41, 0xca, 0xea, 0x98, 0x63, 0xbc, 0x2d, 0xed, 0x5d, 0x5a,
    0xa8, 0x25, 0x3a, 0xa1, 0x0a, 0x2e, 0xf1, 0xc9, 0x8b, 0x9a, 0xc8, 0xb5, 0x7f, 0x11, 0x17, 0xa7,
    0x2b, 0xf2, 0xc7, 0xb9, 0xe7, 0xc1, 0xac, 0x4d, 0x77, 0xfc, 0x94, 0xca, 0xdc, 0x08, 0x3e, 0x67,
    0x98, 0x40, 0x50, 0xb7, 0x5e, 0xba, 0xe5, 0xdd, 0x28, 0x09, 0xbd, 0x63, 0x80, 0x16, 0xf7, 0x23
};

static const uint8_t BRAINPOOL_P512R1_X[] = {
    0x81, 0xae, 0xe4, 0xbd, 0xd8, 0x2e, 0xd9, 0x64, 0x5a, 0x21, 0x32, 0x2e, 0x9c, 0x4c, 0x6a, 0x93,
    0x85, 0xed, 0x9f, 0x70, 0xb5, 0xd9, 0x16, 0xc1, 0xb4, 0x3b, 0x62, 0xee, 0xf4, 0xd0, 0x09, 0x8e,
    0xff, 0x3b, 0x1f, 0x78, 0xe2, 0xd0, 0xd4, 0x8d, 0x50, 0xd1, 0x68, 0x7b, 0x93, 0xb9, 0x7d, 0x5f,
    0x7c, 0x6d, 0x50, 0x47, 0x40, 0x6a, 0x5e, 0x68, 0x8b, 0x35, 0x22, 0x09, 0xbc, 0xb9, 0xf8, 0x22
};

static const uint8_t BRAINPOOL_P512R1_Y[] = {
    0x7d, 0xde, 0x38, 0x5d, 0x56, 0x63, 0x32, 0xec, 0xc0, 0xea, 0xbf, 0xa9, 0xcf, 0x78, 0x22, 0xfd,
    0xf2, 0x09, 0xf7, 0x00, 0x24, 0xa5, 0x7b, 0x1a, 0xa0, 0x00, 0xc5, 0x5b, 0x88, 0x1f, 0x81, 0x11,
    0xb2, 0xdc, 0xde, 0x49, 0x4a, 0x5f, 0x48, 0x5e, 0x5b, 0xca, 0x4b, 0xd8, 0x8a, 0x27, 0x63, 0xae,
    0xd1, 0xca, 0x2b, 0x2f, 0xa8, 0xf0, 0x54, 0x06, 0x78, 0xcd, 0x1e, 0x0f, 0x3a, 0xd8, 0x08, 0x92
};

static const uint8_t BRAINPOOL_P512R1_N[] = {
    0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4, 0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07,
    0xcb, 0x30, 0x8d, 0xb3, 0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33, 0x08, 0x70,
    0x55, 0x3e, 0x5c, 0x41, 0x4c, 0xa9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7f, 0xac, 0x10, 0x47,
    0x1d, 0xb1, 0xd3, 0x81, 0x08, 0x5d, 0xda, 0xdd, 0xb5, 0x87, 0x96, 0x82, 0x9c, 0xa9, 0x00, 0x69
};
#endif

#ifdef HITLS_CRYPTO_CURVE_SM2
static const uint8_t NIST_SM2_P[] = {
    0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

static const uint8_t NIST_SM2_A[] = {
    0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc
};

static const uint8_t NIST_SM2_B[] = {
    0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b, 0xcf, 0x65, 0x09, 0xa7,
    0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92, 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93
};

static const uint8_t NIST_SM2_X[] = {
    0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46, 0x6a, 0x39, 0xc9, 0x94,
    0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1, 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7
};

static const uint8_t NIST_SM2_Y[] = {
    0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3, 0x6b, 0x69, 0x21, 0x53,
    0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40, 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0
};

static const uint8_t NIST_SM2_N[] = {
    0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b, 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23
};
#endif

#if defined(HITLS_CRYPTO_CURVE_NISTP224) || defined(HITLS_CRYPTO_CURVE_NISTP256) || \
    defined(HITLS_CRYPTO_CURVE_NISTP384) || defined(HITLS_CRYPTO_CURVE_NISTP521) || \
    defined(HITLS_CRYPTO_CURVE_SM2)
#define CRYPT_CURVE_PARA_DECLARE(name)              \
    static const CURVE_Para paraNist##name = {      \
        .p.data = NIST_##name##_P,                  \
        .p.dataLen = sizeof(NIST_##name##_P),       \
        .a.data = NIST_##name##_A,                  \
        .a.dataLen = sizeof(NIST_##name##_A),       \
        .b.data = NIST_##name##_B,                  \
        .b.dataLen = sizeof(NIST_##name##_B),       \
        .n.data = NIST_##name##_N,                  \
        .n.dataLen = sizeof(NIST_##name##_N),       \
        .h.data = NIST_P_H,                         \
        .h.dataLen = sizeof(NIST_P_H),              \
        .x.data = NIST_##name##_X,                  \
        .x.dataLen = sizeof(NIST_##name##_X),       \
        .y.data = NIST_##name##_Y,                  \
        .y.dataLen = sizeof(NIST_##name##_Y)        \
    }
#endif

#if defined(HITLS_CRYPTO_CURVE_BP256R1) || defined(HITLS_CRYPTO_CURVE_BP384R1) || defined(HITLS_CRYPTO_CURVE_BP512R1)
#define CRYPT_CURVE_BRAINPOOL_PARA_DECLARE(name)       \
    static const CURVE_Para paraBrainpool##name = {    \
        .p.data = BRAINPOOL_##name##_P,                \
        .p.dataLen = sizeof(BRAINPOOL_##name##_P),     \
        .a.data = BRAINPOOL_##name##_A,                \
        .a.dataLen = sizeof(BRAINPOOL_##name##_A),     \
        .b.data = BRAINPOOL_##name##_B,                \
        .b.dataLen = sizeof(BRAINPOOL_##name##_B),     \
        .n.data = BRAINPOOL_##name##_N,                \
        .n.dataLen = sizeof(BRAINPOOL_##name##_N),     \
        .h.data = BRAINPOOL_P_H,                       \
        .h.dataLen = sizeof(BRAINPOOL_P_H),            \
        .x.data = BRAINPOOL_##name##_X,                \
        .x.dataLen = sizeof(BRAINPOOL_##name##_X),     \
        .y.data = BRAINPOOL_##name##_Y,                \
        .y.dataLen = sizeof(BRAINPOOL_##name##_Y)      \
    }
#endif

#ifdef HITLS_CRYPTO_CURVE_NISTP224
CRYPT_CURVE_PARA_DECLARE(P224);
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP256
CRYPT_CURVE_PARA_DECLARE(P256);
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP384
CRYPT_CURVE_PARA_DECLARE(P384);
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP521
CRYPT_CURVE_PARA_DECLARE(P521);
#endif

#ifdef HITLS_CRYPTO_CURVE_BP256R1
CRYPT_CURVE_BRAINPOOL_PARA_DECLARE(P256R1);
#endif
#ifdef HITLS_CRYPTO_CURVE_BP384R1
CRYPT_CURVE_BRAINPOOL_PARA_DECLARE(P384R1);
#endif
#ifdef HITLS_CRYPTO_CURVE_BP512R1
CRYPT_CURVE_BRAINPOOL_PARA_DECLARE(P512R1);
#endif
#ifdef HITLS_CRYPTO_CURVE_SM2
CRYPT_CURVE_PARA_DECLARE(SM2);
#endif

typedef struct {
    uint32_t id;
    const CURVE_Para *curvePara;
} CURVE_ParaMap;

static const CURVE_ParaMap CURVE_PARAS[] = {
#ifdef HITLS_CRYPTO_CURVE_NISTP224
    { CRYPT_ECC_NISTP224, &paraNistP224 },
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP256
    { CRYPT_ECC_NISTP256, &paraNistP256 },
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP384
    { CRYPT_ECC_NISTP384, &paraNistP384 },
#endif
#ifdef HITLS_CRYPTO_CURVE_NISTP521
    { CRYPT_ECC_NISTP521, &paraNistP521 },
#endif
#ifdef HITLS_CRYPTO_CURVE_BP256R1
    { CRYPT_ECC_BRAINPOOLP256R1, &paraBrainpoolP256R1 },
#endif
#ifdef HITLS_CRYPTO_CURVE_BP384R1
    { CRYPT_ECC_BRAINPOOLP384R1, &paraBrainpoolP384R1 },
#endif
#ifdef HITLS_CRYPTO_CURVE_BP512R1
    { CRYPT_ECC_BRAINPOOLP512R1, &paraBrainpoolP512R1 },
#endif
#ifdef HITLS_CRYPTO_CURVE_SM2
    { CRYPT_ECC_SM2, &paraNistSM2 },
#endif
};

static const CURVE_Para *GetCurvePara(CRYPT_PKEY_ParaId id)
{
    for (uint32_t i = 0; i < sizeof(CURVE_PARAS) / sizeof(CURVE_PARAS[0]); i++) {
        if (CURVE_PARAS[i].id == id) {
            return CURVE_PARAS[i].curvePara;
        }
    }
    BSL_ERR_PUSH_ERROR(CRYPT_ECDH_ERR_UNSUPPORT_CURVE_TYPE);
    return NULL;
}

static int32_t InitMontPara(ECC_Para *para)
{
    if (para->method->bnMontEnc == NULL) {
        return CRYPT_SUCCESS;
    }
    BN_Optimizer *opt = BN_OptimizerCreate();
    para->montP = BN_MontCreate(para->p);
    if (para->montP == NULL || opt == NULL) {
        BN_OptimizerDestroy(opt); // The montP is freed by the caller.
        return CRYPT_MEM_ALLOC_FAIL;
    }
    int32_t ret;
    GOTO_ERR_IF(para->method->bnMontEnc(para->a, para->montP, opt, false), ret);
    GOTO_ERR_IF(para->method->bnMontEnc(para->b, para->montP, opt, false), ret);
ERR:
    BN_OptimizerDestroy(opt);
    return ret;
}

ECC_Para *ECC_NewPara(CRYPT_PKEY_ParaId id)
{
    const CURVE_Para *curve = GetCurvePara(id);
    if (curve == NULL) {
        return NULL;
    }
    const ECC_Method *method = ECC_FindMethod(id);
    if (method == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
        return NULL;
    }
    ECC_Para *para = BSL_SAL_Malloc(sizeof(ECC_Para));
    if (para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        return NULL;
    }
    (void)memset_s(para, sizeof(ECC_Para), 0, sizeof(ECC_Para));
    para->method = method;
    uint32_t bits = curve->p.dataLen * 8; // bits = bytes * 8
    para->id = id;
    para->p = BN_Create(bits);
    para->a = BN_Create(bits);
    para->b = BN_Create(bits);
    para->n = BN_Create(bits);
    para->h = BN_Create(1); // The cofactor is usually 1.
    para->x = BN_Create(bits);
    para->y = BN_Create(bits);

    if (para->p == NULL || para->a == NULL || para->b == NULL || para->n == NULL ||
        para->h == NULL || para->x == NULL || para->y == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        goto ERR;
    }

    int32_t ret;
    GOTO_ERR_IF(BN_Bin2Bn(para->p, curve->p.data, curve->p.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->a, curve->a.data, curve->a.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->b, curve->b.data, curve->b.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->n, curve->n.data, curve->n.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->h, curve->h.data, curve->h.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->x, curve->x.data, curve->x.dataLen), ret);
    GOTO_ERR_IF(BN_Bin2Bn(para->y, curve->y.data, curve->y.dataLen), ret);
    GOTO_ERR_IF(InitMontPara(para), ret);
    return para;
ERR:
    ECC_FreePara(para);
    return NULL;
}

CRYPT_PKEY_ParaId GetCurveId(const CRYPT_EccPara *eccPara)
{
    if (eccPara == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_PKEY_PARAID_MAX;
    }
    int32_t ret;
    BN_BigNum *a = BN_Create(ECC_MAX_BIT_LEN);
    BN_BigNum *b = BN_Create(ECC_MAX_BIT_LEN);

    for (uint32_t i = 0; i < sizeof(CURVE_PARAS) / sizeof(CURVE_ParaMap); i++) {
        const CURVE_Para *curve = GetCurvePara(CURVE_PARAS[i].id);
        if (curve == NULL) {
            continue;
        }
        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->p, eccPara->pLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->p.data, curve->p.dataLen), ret);
        if (BN_Cmp(a, b) != 0) {
            continue;
        }
        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->a, eccPara->aLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->a.data, curve->a.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->b, eccPara->bLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->b.data, curve->b.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->h, eccPara->hLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->h.data, curve->h.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->n, eccPara->nLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->n.data, curve->n.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->x, eccPara->xLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->x.data, curve->x.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        GOTO_ERR_IF_EX(BN_Bin2Bn(a, eccPara->y, eccPara->yLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(b, curve->y.data, curve->y.dataLen), ret);
        BREAK_IF(BN_Cmp(a, b) != 0);

        BN_Destroy(a);
        BN_Destroy(b);
        return CURVE_PARAS[i].id;
    }
ERR:
    BN_Destroy(a);
    BN_Destroy(b);
    return CRYPT_PKEY_PARAID_MAX;
}

int32_t ECC_GetPara(const ECC_Pkey *pkey, CRYPT_EccPara *eccPara)
{
    if (pkey == NULL || eccPara == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (pkey->para == NULL || pkey->para->method == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_PKEY_ERR_EMPTY_KEY);
        return CRYPT_ECC_PKEY_ERR_EMPTY_KEY;
    }
    int32_t ret;
    BN_BigNum *paraA = BN_Dup(pkey->para->a);
    BN_BigNum *paraB = BN_Dup(pkey->para->b);
    if (paraA == NULL || paraB == NULL) {
        ret = CRYPT_MEM_ALLOC_FAIL;
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        goto ERR;
    }
    if (pkey->para->method->bnMontDec != NULL) {
        pkey->para->method->bnMontDec(paraA, pkey->para->montP);
        pkey->para->method->bnMontDec(paraB, pkey->para->montP);
    }
    GOTO_ERR_IF(BN_Bn2Bin(paraA, eccPara->a, &eccPara->aLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(paraB, eccPara->b, &eccPara->bLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(pkey->para->h, eccPara->h, &eccPara->hLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(pkey->para->n, eccPara->n, &eccPara->nLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(pkey->para->p, eccPara->p, &eccPara->pLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(pkey->para->x, eccPara->x, &eccPara->xLen), ret);
    GOTO_ERR_IF(BN_Bn2Bin(pkey->para->y, eccPara->y, &eccPara->yLen), ret);
ERR:
    BN_Destroy(paraA);
    BN_Destroy(paraB);
    return ret;
}

#ifdef HITLS_BSL_PARAMS
int32_t ECC_GetParaEx(const ECC_Pkey *ctx, BSL_Param *para)
{
    if (para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    CRYPT_EccPara eccPara = {0};
    BSL_Param *paramP = GetParamValue(para, CRYPT_PARAM_EC_P, &(eccPara.p), &(eccPara.pLen));
    BSL_Param *paramA = GetParamValue(para, CRYPT_PARAM_EC_A, &(eccPara.a), &(eccPara.aLen));
    BSL_Param *paramB = GetParamValue(para, CRYPT_PARAM_EC_B, &(eccPara.b), &(eccPara.bLen));
    BSL_Param *paramN = GetParamValue(para, CRYPT_PARAM_EC_N, &(eccPara.n), &(eccPara.nLen));
    BSL_Param *paramH = GetParamValue(para, CRYPT_PARAM_EC_H, &(eccPara.h), &(eccPara.hLen));
    BSL_Param *paramX = GetParamValue(para, CRYPT_PARAM_EC_X, &(eccPara.x), &(eccPara.xLen));
    BSL_Param *paramY = GetParamValue(para, CRYPT_PARAM_EC_Y, &(eccPara.y), &(eccPara.yLen));
    int32_t ret = ECC_GetPara(ctx, &eccPara);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }
    paramP->useLen = eccPara.pLen;
    paramA->useLen = eccPara.aLen;
    paramB->useLen = eccPara.bLen;
    paramN->useLen = eccPara.nLen;
    paramH->useLen = eccPara.hLen;
    paramX->useLen = eccPara.xLen;
    paramY->useLen = eccPara.yLen;
    return CRYPT_SUCCESS;
}
#endif

void ECC_FreePara(ECC_Para *para)
{
    if (para == NULL) {
        return;
    }
    BN_Destroy(para->p);
    BN_Destroy(para->a);
    BN_Destroy(para->b);
    BN_Destroy(para->n);
    BN_Destroy(para->h);
    BN_Destroy(para->x);
    BN_Destroy(para->y);
    uint32_t i;
    for (i = 0; i < sizeof(para->tableG) / sizeof(ECC_Point *); i++) {
        // clear pre-computation table
        ECC_FreePoint(para->tableG[i]);
    }
    BN_MontDestroy(para->montP);
    BSL_SAL_Free(para);
}


CRYPT_PKEY_ParaId ECC_GetParaId(const ECC_Para *para)
{
    if (para == NULL) {
        return CRYPT_PKEY_PARAID_MAX;
    }
    return para->id;
}

int32_t ECC_SetPara(ECC_Pkey *ctx, ECC_Para *para)
{
    if (ctx == NULL || para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    // Refresh the public and private keys.
    BN_Destroy(ctx->prvkey);
    ctx->prvkey = NULL;
    ECC_FreePoint(ctx->pubkey);
    ctx->pubkey = NULL;

    ECC_FreePara(ctx->para);
    ctx->para = para;
    ECC_SetLibCtx(ctx->libCtx, ctx->para);

    return CRYPT_SUCCESS;
}

#endif /* HITLS_CRYPTO_ECC */
